/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.item.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gg.reader.api.protocol.gx.LogBaseEpcInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.validation.Valid;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springblade.common.enums.item.ItemOperateType;
import org.springblade.common.exception.TrainingServiceException;
import org.springblade.core.redis.lock.RedisLock;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.item.entity.ItemStockLogEntity;
import org.springblade.modules.item.service.IStockLogService;
import org.springblade.modules.item.vo.InventoryVo;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.modules.item.entity.ItemEntity;
import org.springblade.modules.item.vo.ItemVO;
import org.springblade.modules.item.wrapper.ItemWrapper;
import org.springblade.modules.item.service.IItemService;
import org.springblade.core.boot.ctrl.BladeController;

import java.util.*;


/**
 * 教具 控制器
 *
 * @author junxin
 * @since 2023-03-22
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("blade-item/item")
@Api(value = "教具", tags = "教具接口")
public class ItemController extends BladeController {

	private final IItemService itemService;
	private final IStockLogService stockLogService;

	/**
	 * 教具 详情
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "详情", notes = "传入item")
	public R<ItemVO> detail(ItemEntity item) {
		ItemEntity detail = itemService.getOne(Condition.getQueryWrapper(item));
		return R.data(ItemWrapper.build().entityVO(detail));
	}


	/**
	 * 教具 自定义分页
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/list")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "教具自定义分页", notes = "传入item")
	public R<IPage<ItemVO>> page(ItemVO item, Query query) {
		if (null != item.getValidTimeSearch()) item.setNowTime(DateUtil.format(new Date(), DateUtil.PATTERN_DATETIME));
		IPage<ItemVO> pages = itemService.selectItemPage(Condition.getPage(query), item);
		List<ItemVO> records = pages.getRecords();
		records.forEach(record -> {
			if (null != record.getValidTime() && record.getValidTime().before(new Date())) {
				record.setValidStatus("已过期");
			} else {
				record.setValidStatus("正常");
			}
		});
		return R.data(pages);
	}

	/**
	 * 教具 新增
	 * 新增初始化库存数量、库存总数均为0
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/save")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "新增", notes = "传入item")
	public R save(@Valid @RequestBody ItemEntity item) {
//		item.setStock(0);
//		item.setTotal(0);
		item.setRfidManage(0);
		return R.status(itemService.save(item));
	}

	/**
	 * 教具 修改
	 * 不可修改库存数量
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入item")
	public R update(@Valid @RequestBody ItemEntity item) {
		return R.status(itemService.updateById(item));
	}


	/**
	 * 教具 删除
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "逻辑删除", notes = "传入ids")
	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
		return R.status(itemService.deleteLogic(Func.toLongList(ids)));
	}


	/**
	 * 教具 库存变更
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@RedisLock("lock:item")
	@PostMapping("/stockChange")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "教具库存变更", notes = "变更数量num、变更类型operateType、教具id")
	public R stockChange(@RequestBody ItemVO vo) {
		return R.status(itemService.stockChange(vo));
	}


	/**
	 * 一键盘点
	 */
	//@PreAuth(TrainingRoleConstant.HAS_ROLE_TEACHER)
	@GetMapping("/inventory")
	@ApiOperationSupport(order = 15)
	@ApiOperation(value = "一键盘点", notes = "")
	public R inventory(ItemVO item) {
		InventoryVo result = new InventoryVo();
		//获取当前货架上的教具
		Map<String, LogBaseEpcInfo> map = itemService.inventoryItem();
		int shelvesItems = 0;
		if (CollectionUtil.isNotEmpty(map)) shelvesItems = map.size();

//		if (!map.containsKey(itemEntity.getTid())) {//如果货架上没有该Tid的教具标签
//		}
		ItemEntity itemEntity = itemService.getById(item.getId());
		if (null != itemEntity) {
			result.setTotalNum(itemEntity.getTotal());//总数
			result.setStockNum(itemEntity.getStock());//库存数
			result.setTitle(itemEntity.getItemName() + " 一键盘点:");
			if (StringUtils.isNotBlank(itemEntity.getTid())) {//表示该教具被rfid管理
				if (CollectionUtil.isNotEmpty(map) && map.containsKey(itemEntity.getTid())) {//表示货架上有 默认标签管理的教具都是一个
					int borrowNum = getBorrowNum(item);
					result.setOutNum(borrowNum);
					result.setStockNum(1);
					if (borrowNum > 0) {
						result.setDiffNum(1);
					} else {
						result.setDiffNum(0);
					}
				} else {//表示货架上没有
					//查询借出记录有无登记
					int borrowNum = getBorrowNum(item);
					result.setOutNum(borrowNum);
					int rightNum = itemEntity.getTotal() - borrowNum;//总数-借出数=应有数
					if (rightNum==itemEntity.getStock())result.setDiffNum(0);
					else result.setDiffNum(rightNum-itemEntity.getStock());
				}
			} else {//表示该教具没有被rfid管理
				try {
					//查询借出记录有无登记
					int borrowNum = getBorrowNum(item);
					if (borrowNum<=0){
						result.setOutNum(0);
						result.setDiffNum(0);
					}else {
						result.setOutNum(borrowNum);
						int diffNum = itemEntity.getTotal() - item.getStock() - borrowNum;//总数-库存-借出数
						result.setDiffNum(diffNum);
					}

				}catch (Exception e){
					log.info(e.getMessage());
				}
			}
		}

		return R.data(result);
	}

	public int getBorrowNum(ItemVO item) {
		List<ItemStockLogEntity> list = stockLogService.list(Wrappers.<ItemStockLogEntity>query().lambda().eq(ItemStockLogEntity::getStatus, 2)//待归还状态的
			.eq(ItemStockLogEntity::getItemId, item.getId())
			.eq(ItemStockLogEntity::getType, ItemOperateType.BORROW.getCode())
		);
		int outNum = 0;
		if (CollectionUtil.isNotEmpty(list)) {
			for (ItemStockLogEntity logEntity : list) {
				outNum += logEntity.getNumber();
			}
		}
		return outNum;
	}


	@GetMapping("/return-item")
	@ApiOperationSupport(order = 15)
	@ApiOperation(value = "归还教具", notes = "传入此条记录的id")
	@Transactional(rollbackFor = Exception.class)
	public R returnItem(Long id) {
		ItemStockLogEntity itemStockLogEntity = stockLogService.getById(id);
		if (null != itemStockLogEntity) {

			itemStockLogEntity.setStatus(1);//表示已归还

			ItemEntity itemEntity = itemService.getById(itemStockLogEntity.getItemId());
			if (null != itemEntity) {
				if (StringUtils.isNotBlank(itemEntity.getTid())) {
					//获取当前货架上的教具
					Map<String, LogBaseEpcInfo> map = itemService.inventoryItem();
					if ( CollectionUtil.isEmpty(map) || !map.containsKey(itemEntity.getTid())) {//表示货架上识别不到归还的教具
						throw new TrainingServiceException("货架上未检测到归还的教具");
					}
				}

				itemEntity.setStock(itemStockLogEntity.getNumber() + itemEntity.getStock());
				itemService.updateById(itemEntity);//修改库存数量
			}


			//生成一条归还记录
			ItemStockLogEntity returnItemLog = new ItemStockLogEntity();
			returnItemLog.setType(ItemOperateType.RETURN.getCode().toString());
			returnItemLog.setNumber(itemStockLogEntity.getNumber());
			returnItemLog.setUserId(AuthUtil.getUserId());
			returnItemLog.setItemId(itemStockLogEntity.getItemId());
			returnItemLog.setDeliveryTime(itemStockLogEntity.getDeliveryTime());//出库时间
			returnItemLog.setWarehousingTime(new Date());//归还时间
			returnItemLog.setOperationBackup("归还");
			stockLogService.save(returnItemLog);

			stockLogService.updateById(itemStockLogEntity);//修改待归还的状态 为 已归还
		}

		return R.success("归还成功");
	}

	@GetMapping("/select")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "下拉数据", notes = "传入tenant")
	public R select() {
		QueryWrapper<ItemEntity> queryWrapper = new QueryWrapper<>();
		List<ItemEntity> list = itemService.list();
		return R.data(list);
	}

}
